/*
 * Copyright 2023 Unionman Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <optional>
#include <string>

#include "native_common.h"
#include "napi_error.h"
#include "mslite_errors.h"
#include "mslite_log.h"

namespace OHOS {
namespace MSAI {
namespace {

const std::map<int32_t, std::string> ERROR_MESSAGES = {
    {RETCODE_NULL_PARAM, "Input param is null."},
    {RETCODE_INVALID_PARAM, "Input param is invalid."},
    {RETCODE_PROXY_SEND_REQUEST_FAILED, "Proxy: send request failed."},
    {RETCODE_GET_SA_MANAGER_FAILED, "Proxy: get SA manager failed."},
    {RETCODE_INIT_CLIENT_FAILED, "Proxy: intit client failed."},
    {RETCODE_MINDSPORE_CREATE_CONTEXT_FAILED, "MindSpore: create context failed."},
    {RETCODE_MINDSPORE_CREATE_CPU_DEVICE_INFO_FAILED, "MindSpore: create cpu device info failed."},
    {RETCODE_MINDSPORE_CREATE_NNRT_DEVICE_INFO_FAILED, "MindSpore: create nnrt device info failed."},
    {RETCODE_MINDSPORE_CREATE_MODEL_FAILED, "MindSpore: create model failed."},
    {RETCODE_MINDSPORE_BUILD_MODEL_FAILED, "MindSpore: build model failed."},
    {RETCODE_MINDSPORE_MODEL_NUM_OUT_OF_RANGE, "MindSpore: model num out of range."},
    {RETCODE_MINDSPORE_MODEL_GET_INPUT_FAILED, "MindSpore: model get input failed."},
    {RETCODE_MINDSPORE_TENSOR_GET_MUTABLE_DATA_FAILED, "MindSpore: tensor get mutable data failed."},
    {RETCODE_MINDSPORE_MODEL_PREDICT_FAILED, "MindSpore: model predict failed."},
    {RETCODE_OPENCV_IMDECODE_FAILED, "OpenCV: IMDECODE failed."},
    {RETCODE_JS_PARSE_INPUT_FAILED, "Napi: parse input failed."},
};
}

napi_value CreateBusinessError(const napi_env &env, const int32_t errCode, const std::string &errMessage)
{
    napi_value businessError = nullptr;
    napi_value code = nullptr;
    napi_value msg = nullptr;
    NAPI_CALL(env, napi_create_int32(env, errCode, &code));
    NAPI_CALL(env, napi_create_string_utf8(env, errMessage.c_str(), NAPI_AUTO_LENGTH, &msg));
    napi_create_error(env, nullptr, msg, &businessError);
    napi_set_named_property(env, businessError, "code", code);
    return businessError;
}

std::optional<std::string> GetNapiError(int32_t errorCode)
{
    auto iter = ERROR_MESSAGES.find(errorCode);
    if (iter != ERROR_MESSAGES.end())
    {
        return iter->second;
    }
    return std::nullopt;
}

void ThrowErr(const napi_env &env, const int32_t errCode, const std::string &printMsg)
{
    LOGE("message: %{public}s, code: %{public}d", printMsg.c_str(), errCode);
    auto msg = GetNapiError(errCode);
    if (!msg)
    {
        LOGE("errCode: %{public}d is invalid", errCode);
        return;
    }
    napi_value error = CreateBusinessError(env, errCode, msg.value());
    napi_throw(env, error);
}
} // namespace MSAI
} // namespace OHOS